﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Eqwww.Data;
using Eqwww.Code;
using Eqwww.Domain.Models.SystemManage;
using Eqwww.Domain;
using Microsoft.AspNetCore.Identity;
using Eqwww.Domain.Models.Identity;

namespace Eqwww.App.SystemManage
{
    public class OrganizeApp
    {
        private ApplicationDbContext _context;
        private DatabaseLogApp _dbLogApp;
        private IModelHandler _modelHandler;
        private UserManager<UserModel> _userManager;

        public OrganizeApp(ApplicationDbContext context,
            DatabaseLogApp databaseLogApp,
            IModelHandler modelHandler,
            UserManager<UserModel> userManager)
        {
            _context = context;
            _dbLogApp = databaseLogApp;
            _modelHandler = modelHandler;
            _userManager = userManager;
        }

        public ModelResult Create(OrganizeModel model)
        {
            if (IsCodeExist(model.Code))
                return Common.ErrorResult("编码重复");

            if (string.IsNullOrEmpty(model.ParentId))
                model.Layer = 0;
            else
            {
                var parent = Get(model.ParentId);
                if (parent == null)
                    return Common.ErrorResult("未找到指定的父节点组织");
                model.Layer = parent.Layer + 1;
            }

            _modelHandler.Create(model);
            _context.Add(model);
            _dbLogApp.LogCreateInformation(model.Id, model, "创建组织");
            _context.SaveChanges();
            return Common.SuccessResult();
        }

        public ModelResult Update(OrganizeModel model)
        {
            if (IsCodeExist(model.Code, model.Id))
                return Common.ErrorResult("编码重复");

            if (GetDescendantIdsWithSelf(model.Id).Contains(model.ParentId))
                return Common.ErrorResult("不能将组织移动到自身或子孙组织之下");

            if (!string.IsNullOrEmpty(model.ParentId))
            {
                var newParent = _context.Sys_Organizes.AsNoTracking().FirstOrDefault(x => x.Id == model.ParentId);
                if (newParent == null)
                    return Common.ErrorResult("未找到指定的父节点组织");

                model.Layer = newParent.Layer + 1;
            }
            else
                model.Layer = 0;

            _modelHandler.Update(model);
            _dbLogApp.LogUpdateInformation(model.Id, model, "更新组织");
            _context.SaveChanges();
            return Common.SuccessResult();
        }

        public ModelResult Remove(string id)
        {
            var model = _context.Sys_Organizes.FirstOrDefault(x => x.Id == id);
            if (model == null)
                return Common.ErrorResult("未找到指定id的实体");

            if (_context.Sys_Organizes.Any(x => x.ParentId == id && x.DeleteMark != true))
                return Common.ErrorResult("当前组织有下级组织，不能移除");

            if (_context.Sys_Posts.Any(x => x.OrganizeId == id && x.DeleteMark != true))
                return Common.ErrorResult("当前组织下有岗位，不能移除");

            _modelHandler.Delete(model);
            _dbLogApp.LogRemoveInformation(model.Id, model,"逻辑删除组织");
            _context.SaveChanges();
            return Common.SuccessResult();
        }


        public List<OrganizeModel> GetAllList()
        {
            return _context.Sys_Organizes.Where(x => x.DeleteMark != true).OrderBy(x => x.Name).ToList();
        }


        ///获取指定组织的父路径列表
        public List<OrganizeModel> GetAncestorsWithSelf(string id)
        {
            var list=new List<OrganizeModel>();
            if(string.IsNullOrEmpty(id))
                return list;
            
            var organize=_context.Sys_Organizes.AsNoTracking().FirstOrDefault(x=>x.Id==id);
            if(organize==null)
                return list;
            
            list.Add(organize);

            if(string.IsNullOrEmpty(organize.ParentId))
                return list;

            list.AddRange(GetAncestorsWithSelf(organize.ParentId));
            
            return list;
        }

        ///获取指定id组织的完整名称路径字符串
        public string GetAncestorNamesString(string id, char splitFlag='/')
        {
            var list=GetAncestorsWithSelf(id).OrderBy(x=>x.Layer);
            var str=new StringBuilder();
            foreach(var item in list){
                str.Append(splitFlag.ToString()+item.Name);
            }
            return str.ToString();
        }

        public IEnumerable<string> GetDescendantIdsWithSelf(string id)
        {
            var list = new List<string>();
            if (string.IsNullOrEmpty(id))
                return list;
            list.Add(id);
            var childrenIds = (from p in _context.Sys_Organizes.AsNoTracking().Where(x => x.ParentId == id) select p.Id).ToList();
            if (childrenIds.Count() <= 0)
                return list;
            else
            {
                foreach (var item in childrenIds)
                {
                    list.AddRange(GetDescendantIdsWithSelf(item));
                }
            }
            return list;
        }

        public OrganizeModel Get(string id)
        {
            return _context.Sys_Organizes.AsNoTracking()
                .FirstOrDefault(x => x.Id == id);
        }

        public OrganizeModel GetInclude(string id)
        {
            return _context.Sys_Organizes.AsNoTracking()
                .Include(x=>x.CreateUser)
                .Include(x=>x.LastUpdateUser)
                .Include(x => x.Parent).FirstOrDefault(x => x.Id == id);
        }

        public List<OrganizeModel> GetTreeGridList()
        {
            var data = _context.Sys_Organizes.AsNoTracking().Where(x => x.DeleteMark != true);
            return GetTreeGridList(data.ToList(), null);
        }

        private List<OrganizeModel> GetTreeGridList(List<OrganizeModel> data, string parentId)
        {
            var result = new List<OrganizeModel>();
            var children = data.Where(x => x.ParentId == parentId).OrderBy(x => x.SortCode);
            foreach(var item in children)
            {
                var model = item;
                result.Add(model);
                result.AddRange(GetTreeGridList(data, item.Id));
            }
            return result;
        }

        public bool IsCodeExist(string code)
        {
            return _context.Sys_Organizes.Any(x => x.Code.ToUpper() == code.ToUpper());
        }

        public bool IsCodeExist(string code, string id)
        {
            return _context.Sys_Organizes.Any(x => x.Code.ToUpper() == code.ToUpper() && x.Id != id);
        }

        /// <summary>
        /// 组织选择器
        /// </summary>
        /// <returns></returns>
        public IEnumerable<TreeCollapseModel> GetTreeCollapseItems()
        {
            var data = _context.IQueryable<OrganizeModel>().Where(x => x.DeleteMark != true );
            var result = from item in data
                         select new TreeCollapseModel
                         {
                             Id = item.Id,
                             Text = item.Name,
                             ParentId = item.ParentId,
                             SortCode = item.SortCode,
                             Url = null
                         };
            return result;
        }
    }
}
